// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.globalObjects;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashSet;
import se.krka.kahlua.vm.KahluaTable;
import se.krka.kahlua.vm.KahluaTableIterator;
import zombie.Lua.LuaManager;
import zombie.characters.IsoPlayer;
import zombie.core.BoxedStaticValues;
import zombie.core.Core;
import zombie.core.logger.ExceptionLogger;
import zombie.iso.IsoObject;
import zombie.iso.SliceY;
import zombie.network.GameClient;
import zombie.util.Type;

public final class SGlobalObjectSystem extends GlobalObjectSystem {
    private static KahluaTable tempTable;
    protected int loadedWorldVersion = -1;
    protected final HashSet<String> modDataKeys = new HashSet();
    protected final HashSet<String> objectModDataKeys = new HashSet();
    protected final HashSet<String> objectSyncKeys = new HashSet();

    public SGlobalObjectSystem(String name) {
        super(name);
    }

    @Override
    protected GlobalObject makeObject(int int0, int int1, int int2) {
        return new SGlobalObject(this, int0, int1, int2);
    }

    public void setModDataKeys(KahluaTable kahluaTable) {
        this.modDataKeys.clear();
        if (kahluaTable != null) {
            KahluaTableIterator kahluaTableIterator = kahluaTable.iterator();

            while (kahluaTableIterator.advance()) {
                Object object = kahluaTableIterator.getValue();
                if (!(object instanceof String)) {
                    throw new IllegalArgumentException("expected string but got \"" + object + "\"");
                }

                this.modDataKeys.add((String)object);
            }
        }
    }

    public void setObjectModDataKeys(KahluaTable kahluaTable) {
        this.objectModDataKeys.clear();
        if (kahluaTable != null) {
            KahluaTableIterator kahluaTableIterator = kahluaTable.iterator();

            while (kahluaTableIterator.advance()) {
                Object object = kahluaTableIterator.getValue();
                if (!(object instanceof String)) {
                    throw new IllegalArgumentException("expected string but got \"" + object + "\"");
                }

                this.objectModDataKeys.add((String)object);
            }
        }
    }

    public void setObjectSyncKeys(KahluaTable kahluaTable) {
        this.objectSyncKeys.clear();
        if (kahluaTable != null) {
            KahluaTableIterator kahluaTableIterator = kahluaTable.iterator();

            while (kahluaTableIterator.advance()) {
                Object object = kahluaTableIterator.getValue();
                if (!(object instanceof String)) {
                    throw new IllegalArgumentException("expected string but got \"" + object + "\"");
                }

                this.objectSyncKeys.add((String)object);
            }
        }
    }

    public void update() {
    }

    public void chunkLoaded(int wx, int wy) {
        if (this.hasObjectsInChunk(wx, wy)) {
            Object object = this.modData.rawget("OnChunkLoaded");
            if (object == null) {
                throw new IllegalStateException("OnChunkLoaded method undefined for system '" + this.name + "'");
            } else {
                Double double0 = BoxedStaticValues.toDouble((double)wx);
                Double double1 = BoxedStaticValues.toDouble((double)wy);
                LuaManager.caller.pcall(LuaManager.thread, object, new Object[]{this.modData, double0, double1});
            }
        }
    }

    public void sendCommand(String string, KahluaTable kahluaTable) {
        SGlobalObjectNetwork.sendServerCommand(this.name, string, kahluaTable);
    }

    public void receiveClientCommand(String string, IsoPlayer isoPlayer, KahluaTable kahluaTable) {
        Object object = this.modData.rawget("OnClientCommand");
        if (object == null) {
            throw new IllegalStateException("OnClientCommand method undefined for system '" + this.name + "'");
        } else {
            LuaManager.caller.pcall(LuaManager.thread, object, new Object[]{this.modData, string, isoPlayer, kahluaTable});
        }
    }

    public void addGlobalObjectOnClient(SGlobalObject globalObject) throws IOException {
        if (globalObject == null) {
            throw new IllegalArgumentException("globalObject is null");
        } else if (globalObject.system != this) {
            throw new IllegalArgumentException("object not in this system");
        } else {
            SGlobalObjectNetwork.addGlobalObjectOnClient(globalObject);
        }
    }

    public void removeGlobalObjectOnClient(SGlobalObject globalObject) throws IOException {
        if (globalObject == null) {
            throw new IllegalArgumentException("globalObject is null");
        } else if (globalObject.system != this) {
            throw new IllegalArgumentException("object not in this system");
        } else {
            SGlobalObjectNetwork.removeGlobalObjectOnClient(globalObject);
        }
    }

    public void updateGlobalObjectOnClient(SGlobalObject globalObject) throws IOException {
        if (globalObject == null) {
            throw new IllegalArgumentException("globalObject is null");
        } else if (globalObject.system != this) {
            throw new IllegalArgumentException("object not in this system");
        } else {
            SGlobalObjectNetwork.updateGlobalObjectOnClient(globalObject);
        }
    }

    private String getFileName() {
        return zombie.ZomboidFileSystem.instance.getFileNameInCurrentSave("gos_" + this.name + ".bin");
    }

    public KahluaTable getInitialStateForClient() {
        Object object0 = this.modData.rawget("getInitialStateForClient");
        if (object0 == null) {
            throw new IllegalStateException("getInitialStateForClient method undefined for system '" + this.name + "'");
        } else {
            Object[] object1 = LuaManager.caller.pcall(LuaManager.thread, object0, this.modData);
            return object1 != null && object1[0].equals(Boolean.TRUE) && object1[1] instanceof KahluaTable ? (KahluaTable)object1[1] : null;
        }
    }

    public void OnIsoObjectChangedItself(IsoObject isoObject) {
        GlobalObject globalObject = this.getObjectAt(isoObject.getSquare().x, isoObject.getSquare().y, isoObject.getSquare().z);
        if (globalObject != null) {
            Object object = this.modData.rawget("OnIsoObjectChangedItself");
            if (object == null) {
                throw new IllegalStateException("OnIsoObjectChangedItself method undefined for system '" + this.name + "'");
            } else {
                LuaManager.caller.pcall(LuaManager.thread, object, new Object[]{this.modData, isoObject});
            }
        }
    }

    public int loadedWorldVersion() {
        return this.loadedWorldVersion;
    }

    public void load(ByteBuffer bb, int WorldVersion) throws IOException {
        boolean _boolean = bb.get() == 0;
        if (!_boolean) {
            this.modData.load(bb, WorldVersion);
        }

        int int0 = bb.getInt();

        for (int int1 = 0; int1 < int0; int1++) {
            int int2 = bb.getInt();
            int int3 = bb.getInt();
            byte _byte = bb.get();
            SGlobalObject sGlobalObject = Type.tryCastTo(this.newObject(int2, int3, _byte), SGlobalObject.class);
            sGlobalObject.load(bb, WorldVersion);
        }

        this.loadedWorldVersion = WorldVersion;
    }

    public void save(ByteBuffer bb) throws IOException {
        if (tempTable == null) {
            tempTable = LuaManager.platform.newTable();
        }

        tempTable.wipe();
        KahluaTableIterator kahluaTableIterator = this.modData.iterator();

        while (kahluaTableIterator.advance()) {
            Object object = kahluaTableIterator.getKey();
            if (this.modDataKeys.contains(object)) {
                tempTable.rawset(object, this.modData.rawget(object));
            }
        }

        if (tempTable.isEmpty()) {
            bb.put((byte)0);
        } else {
            bb.put((byte)1);
            tempTable.save(bb);
        }

        bb.putInt(this.objects.size());

        for (int _int = 0; _int < this.objects.size(); _int++) {
            SGlobalObject sGlobalObject = Type.tryCastTo((GlobalObject)this.objects.get(_int), SGlobalObject.class);
            sGlobalObject.save(bb);
        }
    }

    public void load() {
        File file = new File(this.getFileName());

        try {
            FileInputStream fileInputStream = new FileInputStream(file);

            try {
                BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

                try {
                    synchronized (SliceY.SliceBufferLock) {
                        ByteBuffer byteBuffer = SliceY.SliceBuffer;
                        byteBuffer.clear();
                        int int0 = bufferedInputStream.read(byteBuffer.array());
                        byteBuffer.limit(int0);
                        byte byte0 = byteBuffer.get();
                        byte byte1 = byteBuffer.get();
                        byte byte2 = byteBuffer.get();
                        byte byte3 = byteBuffer.get();
                        if (byte0 != 71 || byte1 != 76 || byte2 != 79 || byte3 != 83) {
                            throw new IOException("doesn't appear to be a GlobalObjectSystem file:" + file.getAbsolutePath());
                        }

                        int int1 = byteBuffer.getInt();
                        if (int1 < 134) {
                            throw new IOException("invalid WorldVersion " + int1 + ": " + file.getAbsolutePath());
                        }

                        if (int1 > 195) {
                            throw new IOException("file is from a newer version " + int1 + " of the game: " + file.getAbsolutePath());
                        }

                        this.load(byteBuffer, int1);
                    }
                } catch (Throwable throwable0) {
                    try {
                        bufferedInputStream.close();
                    } catch (Throwable throwable1) {
                        throwable0.addSuppressed(throwable1);
                    }

                    throw throwable0;
                }

                bufferedInputStream.close();
            } catch (Throwable throwable2) {
                try {
                    fileInputStream.close();
                } catch (Throwable throwable3) {
                    throwable2.addSuppressed(throwable3);
                }

                throw throwable2;
            }

            fileInputStream.close();
        } catch (FileNotFoundException fileNotFoundException) {
        } catch (Throwable throwable4) {
            ExceptionLogger.logException(throwable4);
        }
    }

    public void save() {
        if (!Core.getInstance().isNoSave()) {
            if (!GameClient.bClient) {
                File file = new File(this.getFileName());

                try {
                    FileOutputStream fileOutputStream = new FileOutputStream(file);

                    try {
                        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

                        try {
                            synchronized (SliceY.SliceBufferLock) {
                                ByteBuffer byteBuffer = SliceY.SliceBuffer;
                                byteBuffer.clear();
                                byteBuffer.put((byte)71);
                                byteBuffer.put((byte)76);
                                byteBuffer.put((byte)79);
                                byteBuffer.put((byte)83);
                                byteBuffer.putInt(195);
                                this.save(byteBuffer);
                                bufferedOutputStream.write(byteBuffer.array(), 0, byteBuffer.position());
                            }
                        } catch (Throwable throwable0) {
                            try {
                                bufferedOutputStream.close();
                            } catch (Throwable throwable1) {
                                throwable0.addSuppressed(throwable1);
                            }

                            throw throwable0;
                        }

                        bufferedOutputStream.close();
                    } catch (Throwable throwable2) {
                        try {
                            fileOutputStream.close();
                        } catch (Throwable throwable3) {
                            throwable2.addSuppressed(throwable3);
                        }

                        throw throwable2;
                    }

                    fileOutputStream.close();
                } catch (Throwable throwable4) {
                    ExceptionLogger.logException(throwable4);
                }
            }
        }
    }

    @Override
    public void Reset() {
        super.Reset();
        this.modDataKeys.clear();
        this.objectModDataKeys.clear();
        this.objectSyncKeys.clear();
    }
}
